import 'dart:math';
import 'package:decimal/decimal.dart';
import 'model.dart';
import 'model/token_model/token_model.dart';

class VersionBean {
  String? version;
  String? downloadLink;
  String? downloadPage;
  String? description;
  bool? forceUpdate;
  String? currentVersion;
  bool? goNativeDexMarket;

  // bool get valid =>
  //     Utils.isNotEmpty(version) && Utils.isNotEmpty(currentVersion);

  VersionBean.fromJson(Map<String, dynamic> map) {
    version = map['version'];
    downloadLink = map['downloadLink'];
    downloadPage = map['downloadPage'];
    description = map['description'];
    forceUpdate = map['forceUpdate'];
    goNativeDexMarket = map.containsKey('is_show_flutter_market')
        ? map['is_show_flutter_market'] == '1'
        : false;
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['version'] = version;
    data['downloadLink'] = downloadLink;
    data['downloadPage'] = downloadPage;
    data['description'] = description;
    data['forceUpdate'] = forceUpdate;
    data['currentVersion'] = currentVersion;
    data['goNativeDexMarket'] = goNativeDexMarket;
    return data;
  }
}

class DAppBean {
  String? name;
  String? uid;
  String? logo;
  String? url;
  String? description;
  String? statement;
  List<int>? chains;

  DAppBean(
      this.uid, this.name, this.logo, this.url, this.description, this.chains, this.statement);
  DAppBean.optional(
      {this.uid,
      this.name,
      this.logo,
      this.url,
      this.statement='',
      this.description,
      this.chains});
  DAppBean.fromJson(Map<String, dynamic> map) {
    name = map['name'];
    uid = map['uid'];
    logo = map['logo'];
    url = map['url'];
    description = map['description'];
    statement = map['statement'];
    chains = [];
    List<String> chainList = (map['chains'] as String).split(',');
    for (String c in chainList) {
      if (c.isNotEmpty) {
        chains?.add(int.parse(c));
      }
    }
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['name'] = name;
    data['logo'] = logo;
    data['url'] = url;
    data['uid'] = uid;
    data['statement'] = statement;
    data['description'] = description;
    data['chains'] = null == chains ? '' : chains!.join(',');
    return data;
  }

  // List<Chain> getSupportChainList() {
  //   List<Chain> result = [];
  //   chains?.map((chainId) {
  //     if (chainId == Config.tronChainId) {
  //       result.add(ChainList.tronChain);
  //     } else {
  //       for (Chain c in ChainList.chains) {
  //         if (c.type == ChainType.eth &&
  //             null != c.evmInfo &&
  //             c.evmInfo?.chainId == chainId) {
  //           result.add(c);
  //           break;
  //         }
  //       }
  //     }
  //   }).toString();
  //   return result;
  // }

  @override
  String toString() {
    return 'DAppBean{uid: $uid, name: $name, logo: $logo, url: $url, description: $description, chains: $chains, statement: $statement}';
  }
}

class DAppCategoryBean {
  int? categoryId;
  String? name;
  List<DAppBean>? list;

  DAppCategoryBean(this.categoryId, this.name, this.list);

  DAppCategoryBean.fromJson(Map<String, dynamic> map) {
    categoryId = map['category_id'];
    name = map['name'];
    list = [];
    if (null != map['list']) {
      map['list'].forEach((v) {
        list?.add(DAppBean.fromJson(v));
      });
    }
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['name'] = name;
    data['category_id'] = categoryId;
    if (list != null) {
      data['list'] = list!.map((v) => v.toJson()).toList();
    }
    return data;
  }

  @override
  String toString() {
    return 'DAppCategoryBean{categoryId: $categoryId, name: $name, list: $list}';
  }
}

class BannerBean {
  int? id;
  String? name;
  String? link;
  String? image;
  DAppBean? dApp;

  BannerBean({this.id, this.name, this.link, this.image});

  BannerBean.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    name = json['name'];
    link = json['link'];
    image = json['image'];
    if (null != json['dapp']) {
      dApp = DAppBean.fromJson(json['dapp']);
    }
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['id'] = id;
    data['name'] = name;
    data['link'] = link;
    data['image'] = image;
    data['dapp'] = null == dApp ? null : dApp!.toJson();
    return data;
  }

  @override
  String toString() {
    return 'BannerBean{id: $id, name: $name, link: $link, image: $image}';
  }
}

class DAppIndexBean {
  List<BannerBean>? banner;
  List<DAppBean>? hot;
  List<DAppCategoryBean>? category;

  DAppIndexBean(this.banner, this.hot, this.category);

  DAppIndexBean.fromJson(Map<String, dynamic> json) {
    banner = [];
    hot = [];
    category = [];
    if (null != json['banner']) {
      json['banner'].forEach((v) {
        banner?.add(BannerBean.fromJson(v));
      });
    }

    if (null != json['hot']) {
      json['hot'].forEach((v) {
        hot?.add(DAppBean.fromJson(v));
      });
    }

    if (null != json['category']) {
      json['category'].forEach((v) {
        category?.add(DAppCategoryBean.fromJson(v));
      });
    }
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['banner'] =
        null == banner ? [] : banner!.map((e) => e.toJson()).toList();
    data['hot'] = null == hot ? [] : hot!.map((e) => e.toJson()).toList();
    data['category'] =
        null == category ? [] : category!.map((e) => e.toJson()).toList();
    return data;
  }

  @override
  String toString() {
    return 'DAppIndexBean{banner: $banner, hot: $hot, category: $category}';
  }
}

class SwapTokenBean {
  Token? swapToken;

  String? address;
  String? amount;
  String? amountDecimals;
  String? balance;
  String? balanceDecimals;
  String? token;

  SwapTokenBean.fromJson(Map<String, dynamic> json) {
    address = json['address'];
    amount = json['amount'];
    amountDecimals = json['amountDecimals'];
    balance = json['balance'];
    balanceDecimals = json['balanceDecimals'];
    token = json['token'];
  }
}

class NonFungibleTokenMetaSelect {
  int selectedCount;
  NonFungibleTokenMeta tokenMeta;

  NonFungibleTokenMetaSelect({required this.tokenMeta, this.selectedCount = 0});
}

class CrossInfoBean {
  String? minAmount;
  String? feeDesc;
  String? balanceBuy;
  String? balanceSell;
  String? maxAmount;

  CrossInfoBean(
      {this.minAmount,
      this.maxAmount,
      this.feeDesc,
      this.balanceBuy,
      this.balanceSell});

  CrossInfoBean.fromJson(Map<String, dynamic> json) {
    minAmount = json['minAmount'] + ' USDT';
    String fee = json['fee'];
    String feeType = json['feeType'];
    if ("0" == feeType) {
      feeDesc = '$fee%';
    } else {
      feeDesc = '$fee USDT';
    }

    balanceBuy = json['balanceBuy'];
    balanceSell = json['balanceSell'];
  }
}

class MarketTransactionBean {
  String? account;
  String? amount;
  String? hash;
  String? pool;
  String? price;
  int? timestamp;
  int? type;

  MarketTransactionBean.fromJson(Map<String, dynamic> json) {
    account = json['account'];
    amount = json['amount'];
    hash = json['hash'];
    pool = json['pool'];
    price = json['price'];
    timestamp = json['timestamp'];
    type = json['type'];
  }
}

class MarketPriceBean {
  String? price;
  String? reserves0;
  String? reserves1;
  double? usd;
  double? usd24hChange;
  double? usd24hMax;
  double? usd24hMin;
  int? usd24hVol;
  int? holder;

  MarketPriceBean(
      {this.price,
      this.reserves0,
      this.reserves1,
      this.usd,
      this.usd24hChange,
      this.usd24hMax,
      this.usd24hMin,
      this.usd24hVol,
      this.holder});

  MarketPriceBean.fromJson(Map<String, dynamic> json) {
    price = json['price'] ?? '0';
    reserves0 = json['reserves0'] ?? '0';
    reserves1 = json['reserves1'] ?? '0';
    usd = json['usd'] ?? 0;
    usd24hChange = json['usd_24h_change'] ?? 0;
    usd24hMax = json['usd_24h_max'] ?? 0;
    usd24hMin = json['usd_24h_min'] ?? 0;
    usd24hVol = json['usd_24h_vol'] ?? 0;
    holder = json['holder'] ?? 0;
  }
}

class OtcPairListBean {
  int? id;
  int? priceDecimals;
  String? token0Symbol;
  String? token1Symbol;
  String? token0Logo;
  String? token1Logo;
  String? price;
  String? change24h;
  bool? mining;
  bool? fake;

  OtcPairListBean(
      {this.id,
      this.token0Symbol,
      this.token1Symbol,
      this.token0Logo,
      this.token1Logo,
      this.price,
      this.change24h,
      this.mining,
      this.fake});

  OtcPairListBean.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    priceDecimals = json['priceDecimals'];
    token0Symbol = json['token0Symbol'];
    token1Symbol = json['token1Symbol'];
    token0Logo = json['token0Logo'];
    token1Logo = json['token1Logo'];
    price = json['price'];
    change24h = json['change_24h'];
    mining = json['mining'];
    fake = json['fake'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['id'] = id;
    data['priceDecimals'] = priceDecimals;
    data['token0Symbol'] = token0Symbol;
    data['token1Symbol'] = token1Symbol;
    data['token0Logo'] = token0Logo;
    data['token1Logo'] = token1Logo;
    data['price'] = price;
    data['change_24h'] = change24h;
    data['mining'] = mining;
    return data;
  }
}

class OtcDepthCacheBean {
  late int pairId;
  late List<OtcDepthBean> buyDepth;
  late List<OtcDepthBean> sellDepth;

  OtcDepthCacheBean(
      {required this.pairId, required this.buyDepth, required this.sellDepth});

  OtcDepthCacheBean.fromJson(Map<String, dynamic> json) {
    pairId = json['pairId'];
    buyDepth = (json['buyDepth'] as List)
        .map((e) => OtcDepthBean.fromJson(e))
        .toList(growable: false);
    sellDepth = (json['sellDepth'] as List)
        .map((e) => OtcDepthBean.fromJson(e))
        .toList(growable: false);
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['pairId'] = pairId;
    data['buyDepth'] = buyDepth.map((e) => e.toJson()).toList(growable: false);
    data['sellDepth'] =
        sellDepth.map((e) => e.toJson()).toList(growable: false);
    return data;
  }
}

class OtcDepthBean {
  late Decimal price;
  late Decimal amount;
  late Decimal remainAmount;

  OtcDepthBean(
      {required this.price, required this.amount, required this.remainAmount});

  OtcDepthBean.fromJson(Map<String, dynamic> json) {
    price = Decimal.parse(json['price']);
    amount = Decimal.parse(json['amount']);
    remainAmount = Decimal.parse(json['remainAmount']);
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['price'] = price.toString();
    data['amount'] = amount.toString();
    data['remainAmount'] = remainAmount.toString();
    return data;
  }
}

class OtcOrderBean {
  late String id;
  late int pairId;
  late double price;
  late double amount;
  late double remainAmount;
  late int createTime;
  late int dexType;
  late int tradeType;
  late String user;

  OtcOrderBean(this.id, this.pairId, this.price, this.amount, this.remainAmount,
      this.createTime, this.dexType, this.tradeType, this.user);
}

class MiningInfoMean {
  String? total;
  String? person;
  String? excitation;
  String? grandTotal;
  String? waiting;
  String? second;
  String? waitUsdt;
  String? locking;
  String? miningTime;
  String? inviter;

  MiningInfoMean(
      {this.total,
      this.person,
      this.excitation,
      this.grandTotal,
      this.waiting,
      this.second,
      this.waitUsdt,
      this.locking,
      this.miningTime,
      this.inviter});

  MiningInfoMean.fromJson(Map<String, dynamic> json) {
    total = json['total'];
    person = json['person'];
    excitation = json['excitation'];
    grandTotal = json['grandTotal'];
    waiting = json['waiting'];
    second = json['second'];
    waitUsdt = json['waitUsdt'];
    locking = json['locking'];
    miningTime = json['miningTime'];
    inviter = json['inviter'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['total'] = total;
    data['person'] = person;
    data['excitation'] = excitation;
    data['grandTotal'] = grandTotal;
    data['waiting'] = waiting;
    data['second'] = second;
    data['waitUsdt'] = waitUsdt;
    data['locking'] = locking;
    data['miningTime'] = miningTime;
    data['inviter'] = inviter;
    return data;
  }
}

class MiningPairInfoMean {
  String? total;
  String? person;
  String? excitation;
  String? grandTotal;
  String? waiting;
  String? second;
  String? waitUsdt;
  String? locking;

  MiningPairInfoMean(
      {this.total,
      this.person,
      this.excitation,
      this.grandTotal,
      this.waiting,
      this.second,
      this.waitUsdt,
      this.locking});

  MiningPairInfoMean.fromJson(Map<String, dynamic> json) {
    total = json['total'];
    person = json['person'];
    excitation = json['excitation'];
    grandTotal = json['grandTotal'];
    waiting = json['waiting'];
    second = json['second'];
    waitUsdt = json['waitUsdt'];
    locking = json['locking'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['total'] = total;
    data['person'] = person;
    data['excitation'] = excitation;
    data['grandTotal'] = grandTotal;
    data['waiting'] = waiting;
    data['second'] = second;
    data['waitUsdt'] = waitUsdt;
    data['locking'] = locking;
    return data;
  }
}

class OtcInfoBean {
  late Decimal price;
  late int priceDecimals;
  late String token0;
  late int token0Decimals;
  late String token1;
  late int token1Decimals;
  late Decimal token0Balance;
  late Decimal token1Balance;
  late List<OtcDepthBean> buyDepth;
  late List<OtcDepthBean> sellDepth;

  late List<OtcOrderBean> activeOrders;

  late int tradeLimitMinRate;
  late int tradeLimitMaxRate;
  late int tradeMarketBuyRate;
  late int tradeMarketSellRate;

  OtcInfoBean(
      {required this.price,
      required this.priceDecimals,
      required this.token0,
      required this.token0Decimals,
      required this.token1,
      required this.token1Decimals,
      required this.token0Balance,
      required this.token1Balance,
      required this.buyDepth,
      required this.sellDepth,
      required this.activeOrders});

  OtcInfoBean.fromJson(Map<String, dynamic> json) {
    priceDecimals = int.parse(json['priceDecimals']);
    price = (Decimal.parse(json['price']) /
            Decimal.ten.pow(priceDecimals).toDecimal())
        .toDecimal(scaleOnInfinitePrecision: priceDecimals);
    token0 = json['token0'];
    token0Decimals = int.parse(json['token0Decimals']);
    token1 = json['token1'];
    token1Decimals = int.parse(json['token1Decimals']);
    token0Balance = (Decimal.parse(json['token0Balance']) /
            Decimal.ten.pow(token0Decimals).toDecimal())
        .toDecimal(scaleOnInfinitePrecision: token0Decimals);
    token1Balance = (Decimal.parse(json['token1Balance']) /
            Decimal.ten.pow(token1Decimals).toDecimal())
        .toDecimal(scaleOnInfinitePrecision: token1Decimals);

    tradeLimitMinRate = int.parse(json['tradeLimitMinRate']);
    tradeLimitMaxRate = int.parse(json['tradeLimitMaxRate']);
    tradeMarketBuyRate = int.parse(json['tradeMarketBuyRate']);
    tradeMarketSellRate = int.parse(json['tradeMarketSellRate']);

    List<Decimal> buyPrices = (json['buyPrices'] as List)
        .map((e) =>
            (Decimal.parse(e) / Decimal.ten.pow(priceDecimals).toDecimal())
                .toDecimal(scaleOnInfinitePrecision: priceDecimals))
        .toList(growable: false);
    List<Decimal> buyAmounts = (json['buyAmounts'] as List)
        .map((e) =>
            (Decimal.parse(e) / Decimal.ten.pow(token0Decimals).toDecimal())
                .toDecimal(scaleOnInfinitePrecision: token0Decimals))
        .toList(growable: false);
    List<Decimal> buyRemainAmounts = (json['buyRemainAmounts'] as List)
        .map((e) =>
            (Decimal.parse(e) / Decimal.ten.pow(token1Decimals).toDecimal())
                .toDecimal(scaleOnInfinitePrecision: token1Decimals))
        .toList(growable: false);

    buyDepth = [];
    for (int i = 0; i < buyPrices.length; i++) {
      buyDepth.add(OtcDepthBean(
          price: buyPrices[i],
          amount: buyAmounts[i],
          remainAmount: buyRemainAmounts[i]));
    }

    List<Decimal> sellPrices = (json['sellPrices'] as List)
        .map((e) =>
            (Decimal.parse(e) / Decimal.ten.pow(priceDecimals).toDecimal())
                .toDecimal(scaleOnInfinitePrecision: priceDecimals))
        .toList(growable: false);
    List<Decimal> sellAmounts = (json['sellAmounts'] as List)
        .map((e) =>
            (Decimal.parse(e) / Decimal.ten.pow(token0Decimals).toDecimal())
                .toDecimal(scaleOnInfinitePrecision: token0Decimals))
        .toList(growable: false);
    List<Decimal> sellRemainAmounts = (json['sellRemainAmounts'] as List)
        .map((e) =>
            (Decimal.parse(e) / Decimal.ten.pow(token1Decimals).toDecimal())
                .toDecimal(scaleOnInfinitePrecision: token1Decimals))
        .toList(growable: false);

    sellDepth = [];
    for (int i = 0; i < sellPrices.length; i++) {
      sellDepth.add(OtcDepthBean(
          price: sellPrices[i],
          amount: sellAmounts[i],
          remainAmount: sellRemainAmounts[i]));
    }

    if (json['activeOrders'] != null) {
      activeOrders = (json['activeOrders'] as List).map((e) {
        double orderPrice = double.parse(e['price']) / pow(10, priceDecimals);
        double orderAmount =
            double.parse(e['amount']) / pow(10, token0Decimals);
        double orderRemainAmount =
            double.parse(e['remainAmount']) / pow(10, token0Decimals);
        return OtcOrderBean(
            e['id'],
            int.parse(e['pairId']),
            orderPrice,
            orderAmount,
            orderRemainAmount,
            int.parse(e['createTime']),
            int.parse(e['dexType']),
            int.parse(e['tradeType']),
            e['user']);
      }).toList(growable: false);
    } else {
      activeOrders = [];
    }
  }
}

class OtcDealOrderBean {
  late bool buy;
  late int createTime;
  late int dealTime;
  late String dealPrice;
  late String deputePrice;
  late String dealAmount;
  late String realDealAmount;
  late String dealAmountValue;
  late String deputeAmount;
  late bool dealWhole;
  late String hash;
  late bool tradeType;
  late String feeAmount;

  OtcDealOrderBean.fromJson(Map<String, dynamic> json) {
    buy = json['dexType'] == 0 ? true : false;
    tradeType = json['tradeType'] == 0 ? true : false;
    createTime = json['createTime'];
    dealTime = json['dealTime'];
    dealPrice = json['dealPrice'];
    deputePrice = json['deputePrice'];
    dealAmount = json['dealAmount'];
    realDealAmount = json['realDealAmount'];
    dealAmountValue = json['dealAmountValue'];
    deputeAmount = json['deputeAmount'];
    dealWhole = json['dealWhole'];
    hash = json['hash'];
    feeAmount = json['feeAmount'];
  }
}

class NoticeListBean {
  late String id;
  late String title;
  late String describe;
  late String content;
  late int createTime;
  late bool isShowInfo;
  late bool isRead;

  NoticeListBean(
      this.title, this.content, this.createTime, this.isShowInfo, this.isRead);

  NoticeListBean.fromJson(Map<String, dynamic> json) {
    id = json['id'].toString();
    title = json['title'];
    describe = json['describe_info'] ?? '';
    content = json['content'] ?? '';
    createTime = json['created_time'];
    isShowInfo = '1' == json['is_show_info'];
    isRead = '1' == json['is_read'];
  }
}

class Token20Bean {
  late String name;
  late String symbol;
  late String contract;
  late String balance;
  late int decimals;
  late String priceUsd;
  late String valueUsd;

  Token20Bean(this.name, this.symbol, this.contract, this.balance,
      this.decimals, this.priceUsd, this.valueUsd);

  Token20Bean.fromJson(Map<String, dynamic> json) {
    name = json['name'] ?? ' ';
    symbol = json['symbol'] ?? ' ';
    contract = json['contract'];
    balance = json['balance'] ?? '0';
    decimals = json['decimals'] ?? 0;
    priceUsd = json['price_usd'] ?? '0';
    valueUsd = json['value_usd'] ?? '0';
  }
}
